<?php

namespace C\S\Shipment;

use C\L\Service;
use C\M\Shipment as ShipmentModel;
use C\M\GroupBuyingUserOrder;
use C\P\Http;

class Shipment extends Service
{
    private $companies = [
    ['name' => '中通快递', 'pinyin' => 'zhongtong', 'tel' => '95311'],
    ['name' => '圆通快递', 'pinyin' => 'yuantong', 'tel' => '95554'],
    ['name' => '申通快递', 'pinyin' => 'shentong', 'tel' => '95543'],
    ['name' => '百世快递', 'pinyin' => 'baishi', 'tel' => '95320'],
    ['name' => '韵达快递', 'pinyin' => 'yunda', 'tel' => '95546'],
    ['name' => '顺丰速运', 'pinyin' => 'shunfeng', 'tel' => '95338'],
    ['name' => 'EMS', 'pinyin' => 'ems', 'tel' => '11183'],
    ['name' => '天天快递', 'pinyin' => 'tiantian', 'tel' => '4001888888'],
    ['name' => '邮政包裹信件', 'pinyin' => 'youzhengguonei', 'tel' => '11183'],
    ['name' => '京东快递', 'pinyin' => 'jingdong', 'tel' => '950616'],
    ];

    protected function setModel()
    {
        $this->model = new \C\M\Shipment();
    }

    public function ship($shipableId, $shipableType, $company, $waybillNumber)
    {
        $shipable = null;
        $receiver = null;
        switch ($shipableType) {
            case 'group_buying_user_order':
                $shipable = GroupBuyingUserOrder::findById($shipableId);
                $receiver = $this->getReceiverFromGroupBuyingUserOrder($shipable);
                break;
            default:
                break;
        }

        if (!$shipable) {
            throw new \Exception('未找到对应资源');
        }

        if (!$receiver) {
            throw new \Exception('未找到对应收货地址');
        }

        $queryResult = $this->queryFromKuaiDi100($company, $waybillNumber, $receiver['tel']);
        if (isset($queryResult['returnCode']) && $queryResult['returnCode'] != 200) {
            throw new \Exception($queryResult['message']);
        }

        $subscribeResult = $this->subscribeFromKuaiDi100($company, $waybillNumber, $receiver['tel']);
        if (!$subscribeResult['result']) {
            throw new \Exception($subscribeResult['message']);
        }

        $shipment = new ShipmentModel();
        $shipment->shipable_id      = $shipableId;
        $shipment->shipable_type    = $shipableType;
        $shipment->company          = $company;
        $shipment->waybill_number   = $waybillNumber;
        $shipment->receiver_name    = $receiver['name'];
        $shipment->receiver_tel     = $receiver['tel'];
        $shipment->receiver_address = $receiver['province'] . $receiver['city'] . $receiver['county'] . $receiver['address'];
        $shipment->state            = 'shipped';
        $shipment->traces           = json_encode($queryResult['data']);
        $shipment->other_info       = json_encode($queryResult);

        $result = $shipment->save();
        if (!$result) {
            throw new \Exception('添加物流记录失败');
        }

        return true;
    }

    public function updateByKuaidi100($data)
    {
        $lastResult = $data['lastResult'];
        if (!$lastResult) {
            throw new \Exception('数据有误');
        }

        $waybillNumber = $lastResult['nu'] ?? -1;
        $shipment = ShipmentModel::findFirst([
        'waybill_number = :waybill_number:',
        'bind' => ['waybill_number' => $waybillNumber],
        ]);
        if (!$shipment) {
            throw new \Exception('未找到物流单');
        }

        $shipment->traces = json_encode($lastResult['data']);
        $shipment->other_info = json_encode($data);

        return $shipment->save();
    }

    private function getReceiverFromGroupBuyingUserOrder($order)
    {
        $otherInfo = json_decode($order->other_info, true);
        return $otherInfo['address'];
    }

    private function subscribeFromKuaiDi100($companyName, $waybillNumber, $phone)
    {
        $companyIndex = array_search($companyName, array_column($this->companies, 'name'));
        if ($companyIndex === false) {
            throw new \Exception('未知物流公司');
        }

        $company = $this->companies[$companyIndex];

        $config = $this->di['config']->get('config')->kuaidi100_config;
        $param = [
        'company'    => $company['pinyin'] ?? '',
        'number'     => $waybillNumber,
        'from'       => '',
        'to'         => '',
        'key'        => $config['key'] ?? '',
        'parameters' => [
        'callbackurl'        => $config['callback_url'] ?? '',
        'salt'               => '',
        'resultv2'           => 1,
        'autoCom'            => 0,
        'interCom'           => 0,
        'departureCountry'   => '',
        'departureCom'       => '',
        'destinationCountry' => '',
        'destinationCom'     => '',
        'phone'              => $phone,
        ],
        ];
        $requestBody = [
        'schema' => 'json',
        'param'  => json_encode($param),
        ];
        $result = Http::post($config['subscribe_url'], $requestBody);

        return json_decode($result, true);
    }

    private function queryFromKuaiDi100($companyName, $waybillNumber, $phone)
    {
        $companyIndex = array_search($companyName, array_column($this->companies, 'name'));
        if ($companyIndex === false) {
            throw new \Exception('未知物流公司');
        }

        $company = $this->companies[$companyIndex];

        $config = $this->di['config']->get('config')->kuaidi100_config;

        $param = [
        'com'  => $company['pinyin'] ?? '',
        'num'      => $waybillNumber,
        'phone'    => $phone,
        'from'     => '',
        'to'       => '',
        'resultv2' => '1',
        'show'     => '0',
        'order'    => 'desc',
        ];

        $sign = $this->generateKuaiDi100Sign($param, $config['key'], $config['customer']);

        $requestBody = [
        'customer' => $config['customer'],
        'sign'     => $sign,
        'param'    => json_encode($param),
        ];

        $result = Http::post($config['query_url'], $requestBody);

        return json_decode($result, true);
    }

    private function generateKuaiDi100Sign($param, $key, $customer)
    {
        return strtoupper(md5(json_encode($param) . $key . $customer));
    }
}
